import subprocess
import os
from datetime import datetime
import json
import threading
import re

class TextToSpeech:
    def __init__(self):
        self.history_file = 'app/data/tts_history.json'
        self._ensure_history_file()
    
    def _ensure_history_file(self):
        """确保历史记录文件存在"""
        os.makedirs(os.path.dirname(self.history_file), exist_ok=True)
        if not os.path.exists(self.history_file):
            with open(self.history_file, 'w') as f:
                json.dump([], f)
    
    def speak(self, text, voice_type='female', speed=50, pitch=50, volume=80):
        """主入口：文本转语音并异步分段播放"""
        if not text:
            return False, "文本不能为空"
        try:
            # 需按句子进行断句，按英文单词进行断句，放置播报时出现卡顿，不自然的情况
            segments = self._split_text(text, max_len=15) 
            threading.Thread(
                target=self._async_speak_segments,
                args=(segments, voice_type, speed, pitch, volume),
                daemon=True
            ).start()
            return True, "已开始播报"
        except Exception as e:
            return False, f"播报失败: {str(e)}"
    
    def _split_text(self, text, max_len=15):
        """按max_len分割文本，优先按标点断句"""
        sentences = re.split(r'([。！？；,.!?;])', text)
        result, buf = [], ''
        for s in sentences:
            buf += s
            if len(buf) >= max_len or s in '。！？；,.!?;':
                if buf.strip():
                    result.append(buf.strip())
                buf = ''
        if buf.strip():
            result.append(buf.strip())
        return [seg for seg in result if seg]
    
    def _async_speak_segments(self, segments, voice_type, speed, pitch, volume):
        for seg in segments:
            wav_path = '/tmp/tts.wav'
            cmd = self._build_espeak_command(seg, voice_type, speed, pitch, volume, wav_path)
            self._synthesize_to_wav(cmd)
            self._play_wav(wav_path)
            self._save_history(seg, voice_type, speed, pitch, volume)
    
    def _build_espeak_command(self, text, voice_type, speed, pitch, volume, wav_path):
        """生成espeak命令"""
        voice_map = {
            'female': 'zh+f2',
            'male': 'zh+m1',
            'child': 'zh+f3'
        }
        voice = voice_map.get(voice_type, 'zh+f2')
        speed = max(0, min(200, speed * 2))
        pitch = max(0, min(99, pitch))
        volume = max(0, min(200, volume * 2))
        cmd = f'espeak -v {voice} -s {speed} -p {pitch} -a {volume} -w {wav_path} "{text}"'
        return cmd
    
    def _synthesize_to_wav(self, cmd):
        """调用espeak生成wav文件"""
        subprocess.run(cmd, shell=True, check=True)
    
    def _play_wav(self, wav_path):
        """播放wav文件"""
        subprocess.run(f'aplay {wav_path}', shell=True, check=True)
    
    def _save_history(self, text, voice_type, speed, pitch, volume):
        """保存合成历史"""
        try:
            # 读取现有历史
            with open(self.history_file, 'r') as f:
                history = json.load(f)
            
            # 添加新记录
            history.append({
                'time': datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
                'text': text,
                'voice_type': voice_type,
                'speed': speed,
                'pitch': pitch,
                'volume': volume
            })
            
            # 只保留最近100条记录
            history = history[-100:]
            
            # 保存历史
            with open(self.history_file, 'w') as f:
                json.dump(history, f, ensure_ascii=False, indent=2)
                
        except Exception as e:
            print(f"保存历史记录失败: {str(e)}")
    
    def get_history(self, limit=10):
        """获取合成历史
        
        Args:
            limit (int): 返回的记录数量
            
        Returns:
            list: 历史记录列表
        """
        try:
            with open(self.history_file, 'r') as f:
                history = json.load(f)
            return history[-limit:]
        except Exception as e:
            print(f"读取历史记录失败: {str(e)}")
            return [] 